﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Afk.ZoneInfo;
using System.Globalization;

namespace ConsoleZoneInfo
{
    class Program
    {
        private enum WeekOfMonth
        {
            First = 1,
            Second = 2,
            Third = 3,
            Fourth = 4,
            Last = 5,
        }

        static void Main(string[] args)
        {
            NewYork();

            //DateTime local = Zones.Europe.Paris.ToLocalTime(DateTime.UtcNow);

            //foreach (TimeZoneInfo z in TimeZoneInfo.GetSystemTimeZones())
            //    Console.WriteLine(z.Id);

            //DateTime thisTime = DateTime.Now;
            //Console.WriteLine("Time in {0} zone: {1}", TimeZoneInfo.Local.IsDaylightSavingTime(thisTime) ?
            //                  TimeZoneInfo.Local.DaylightName : TimeZoneInfo.Local.StandardName, thisTime);
            //Console.WriteLine("   UTC Time: {0}", TimeZoneInfo.ConvertTimeToUtc(thisTime, TimeZoneInfo.Local));
            //// Get Tokyo Standard Time zone
            //TimeZoneInfo tst = TimeZoneInfo.FindSystemTimeZoneById("Tokyo Standard Time");
            //DateTime tstTime = TimeZoneInfo.ConvertTime(thisTime, TimeZoneInfo.Local, tst);
            //Console.WriteLine("Time in {0} zone: {1}", TimeZoneInfo.Local.IsDaylightSavingTime(tstTime) ?
            //                  tst.DaylightName : tst.StandardName, tstTime);
            //Console.WriteLine("   UTC Time: {0}", TimeZoneInfo.ConvertTimeToUtc(tstTime, tst));

            //TimeZoneInfo tstSamoa = TimeZoneInfo.FindSystemTimeZoneById("Samoa Standard Time");
            //DateTime utc = new DateTime(2011, 12, 29, 0, 0, 0, DateTimeKind.Utc);
            //Console.WriteLine("UTC \t\t\t| Samoa Local Time");
            //for (int i = 1; i <= 48; i++)
            //{
            //    utc = utc.AddHours(1);
            //    Console.WriteLine(utc + "\t| " + TimeZoneInfo.ConvertTimeFromUtc(utc, tstSamoa));
            //}
            //Console.ReadLine();

            //var atz = Zones.Pacific.Apia;
            //utc = new DateTime(2011, 12, 29, 0, 0, 0, DateTimeKind.Utc);
            //Console.WriteLine("UTC \t\t\t| Samoa Local Time");
            //for (int i = 1; i <= 48; i++)
            //{
            //    utc = utc.AddHours(1);
            //    Console.WriteLine(utc + "\t| " + atz.ToLocalTime(utc));
            //}
            //Console.ReadLine();

        }

        static void NewYork()
        {
            var tz = Zones.America.New_York;

            var windows = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
            WriteAdjustementRules(windows);
            //WriteAdjustementRules(tz);

            DateTime old = new DateTime(2006, 4, 2, 0, 0, 0, DateTimeKind.Utc);
            for (int i = 1; i <= 24; i++)
            {
                old = old.AddHours(1);
                Console.WriteLine(old + "\t| " + tz.ToLocalTime(old));
            }

            Console.ReadLine();
            Console.WriteLine("------ TimeZoneInfo C#");
            old = new DateTime(2006, 4, 2, 0, 0, 0, DateTimeKind.Utc);
            for (int i = 1; i <= 24; i++)
            {
                old = old.AddHours(1);
                Console.WriteLine(old + "\t| " + TimeZoneInfo.ConvertTimeFromUtc(old, windows));
            }
            Console.ReadLine();
        }

        static void WriteAdjustementRules(TimeZoneInfo tinfo)
        {
            var adjustments = tinfo.GetAdjustmentRules();

            string[] monthNames = CultureInfo.CurrentCulture.DateTimeFormat.MonthNames;
   
            // Handle time zones with 1 or 2+ adjustments differently 
            bool showCount = false;
            int ctr = 0;
            string spacer = "";

            Console.WriteLine("{0} Adjustment rules", tinfo.StandardName);
            if (adjustments.Length > 1)
            {
                showCount = true;
                spacer = "   ";
            }   

            // Iterate adjustment rules 
            foreach (TimeZoneInfo.AdjustmentRule adjustment in adjustments)
            {
                if (showCount)
                {
                    Console.WriteLine("   Adjustment rule #{0}", ctr + 1);
                    ctr++;
                }
                // Display general adjustment information
                Console.WriteLine("{0}   Start Date: {1:D}", spacer, adjustment.DateStart);
                Console.WriteLine("{0}   End Date: {1:D}", spacer, adjustment.DateEnd);
                Console.WriteLine("{0}   Time Change: {1}:{2:00} hours", spacer,
                                  adjustment.DaylightDelta.Hours, adjustment.DaylightDelta.Minutes);
                // Get transition start information
                TimeZoneInfo.TransitionTime transitionStart = adjustment.DaylightTransitionStart;
                Console.Write("{0}   Annual Start: ", spacer);
                if (transitionStart.IsFixedDateRule)
                {
                    Console.WriteLine("On {0} {1} at {2:t}",
                                      monthNames[transitionStart.Month - 1],
                                      transitionStart.Day,
                                      transitionStart.TimeOfDay);
                }
                else
                {
                    Console.WriteLine("The {0} {1} of {2} at {3:t}",
                                      ((WeekOfMonth)transitionStart.Week).ToString(),
                                      transitionStart.DayOfWeek.ToString(),
                                      monthNames[transitionStart.Month - 1],
                                      transitionStart.TimeOfDay);
                }
                // Get transition end information
                TimeZoneInfo.TransitionTime transitionEnd = adjustment.DaylightTransitionEnd;
                Console.Write("{0}   Annual End: ", spacer);
                if (transitionEnd.IsFixedDateRule)
                {
                    Console.WriteLine("On {0} {1} at {2:t}",
                                      monthNames[transitionEnd.Month - 1],
                                      transitionEnd.Day,
                                      transitionEnd.TimeOfDay);
                }
                else
                {
                    Console.WriteLine("The {0} {1} of {2} at {3:t}",
                                      ((WeekOfMonth)transitionEnd.Week).ToString(),
                                      transitionEnd.DayOfWeek.ToString(),
                                      monthNames[transitionEnd.Month - 1],
                                      transitionEnd.TimeOfDay);
                }
            }
        }

        //static void WriteAdjustementRules(TzTimeZone tinfo)
        //{
        //    var adjustments = tinfo.GetAdjustmentRules();

        //    string[] monthNames = CultureInfo.CurrentCulture.DateTimeFormat.MonthNames;

        //    // Handle time zones with 1 or 2+ adjustments differently 
        //    bool showCount = false;
        //    int ctr = 0;
        //    string spacer = "";

        //    Console.WriteLine("{0} Adjustment rules", tinfo.Name);
        //    if (adjustments.Length > 1)
        //    {
        //        showCount = true;
        //        spacer = "   ";
        //    }

        //    // Iterate adjustment rules 
        //    foreach (var adjustment in adjustments)
        //    {
        //        if (showCount)
        //        {
        //            Console.WriteLine("   Adjustment rule #{0}", ctr + 1);
        //            ctr++;
        //        }
        //        // Display general adjustment information
        //        Console.WriteLine("{0}   Start Date: {1:D}", spacer, adjustment.DateStart);
        //        Console.WriteLine("{0}   End Date: {1:D}", spacer, adjustment.DateEnd);
        //        //Console.WriteLine("{0}   Time Change: {1}:{2:00} hours", spacer,
        //        //                  adjustment.DaylightDelta.Hours, adjustment.DaylightDelta.Minutes);
        //        //// Get transition start information
        //        //TimeZoneInfo.TransitionTime transitionStart = adjustment.DaylightTransitionStart;
        //        //Console.Write("{0}   Annual Start: ", spacer);
        //        //if (transitionStart.IsFixedDateRule)
        //        //{
        //        //    Console.WriteLine("On {0} {1} at {2:t}",
        //        //                      monthNames[transitionStart.Month - 1],
        //        //                      transitionStart.Day,
        //        //                      transitionStart.TimeOfDay);
        //        //}
        //        //else
        //        //{
        //        //    Console.WriteLine("The {0} {1} of {2} at {3:t}",
        //        //                      ((WeekOfMonth)transitionStart.Week).ToString(),
        //        //                      transitionStart.DayOfWeek.ToString(),
        //        //                      monthNames[transitionStart.Month - 1],
        //        //                      transitionStart.TimeOfDay);
        //        //}
        //        //// Get transition end information
        //        //TimeZoneInfo.TransitionTime transitionEnd = adjustment.DaylightTransitionEnd;
        //        //Console.Write("{0}   Annual End: ", spacer);
        //        //if (transitionEnd.IsFixedDateRule)
        //        //{
        //        //    Console.WriteLine("On {0} {1} at {2:t}",
        //        //                      monthNames[transitionEnd.Month - 1],
        //        //                      transitionEnd.Day,
        //        //                      transitionEnd.TimeOfDay);
        //        //}
        //        //else
        //        //{
        //        //    Console.WriteLine("The {0} {1} of {2} at {3:t}",
        //        //                      ((WeekOfMonth)transitionEnd.Week).ToString(),
        //        //                      transitionEnd.DayOfWeek.ToString(),
        //        //                      monthNames[transitionEnd.Month - 1],
        //        //                      transitionEnd.TimeOfDay);
        //        //}
        //    }
        //}
    }
}
